package com.lkd.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lkd.entity.Task;
import com.lkd.entity.TaskType;
import com.lkd.mapper.TaskMapper;
import com.lkd.service.ITaskService;
import com.lkd.service.ITaskTypeService;
import com.lkd.vo.TaskVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * <p>
 * 工单表 服务实现类
 * </p>
 *
 * @author xiaotao
 * @since 2025-10-19
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements ITaskService {

    private final ITaskTypeService taskTypeService;

    /** 常量定义 */
    private static final int TYPE_REPAIR  = 1;
    private static final int TYPE_OPERATE = 2;

    /**
     * 工单统计(借鉴别人版本)
     *
     * @param start 开始日期
     * @param end   结束日期
     * @return 返回工单查询结果
     */
    @Override
    public List<TaskVo> taskReportInfo(String start, String end) {
        LambdaQueryWrapper<Task> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.ge(Task::getCreateTime,start)
                .le(Task::getCreateTime,end);
        List<Task> list = list(queryWrapper);
        //运维工单
        List<Task> repairList = new ArrayList<>();
        //运营工单
        List<Task> operateList = new ArrayList<>();
        for (Task task : list) {
            TaskType taskType = taskTypeService.getById(task.getProductTypeId());
            if ( taskType.getType() == 1){
                repairList.add(task);
            }else {
                operateList.add(task);
            }
        }
        //封装运维工单数据
        TaskVo repairVo = workOrderData(repairList,true);
        //封装运营工单数据
        TaskVo operateVo = workOrderData(operateList,false);
        List<TaskVo> taskVoList = new ArrayList<>();
        taskVoList.add(repairVo);
        taskVoList.add(operateVo);
        return taskVoList;
    }

    private TaskVo workOrderData(List<Task> taskList, boolean b) {
        //封装运维工单数据
        TaskVo taskVo = new TaskVo();
        taskVo.setTotal(taskList.size()); //运维工单总数
        Integer completedTotal = (int) taskList.stream().filter(task -> task.getTaskStatus() == 4).count();
        taskVo.setCompletedTotal(completedTotal);//运维工单完成总数
        Integer cancelTotal= (int) taskList.stream().filter(task -> task.getTaskStatus() == 3).count();
        taskVo.setCancelTotal(cancelTotal);//运维工单取消总数
        Integer progressTotal = (int) taskList.stream().filter(task -> task.getTaskStatus() == 2).count();
        taskVo.setProgressTotal(progressTotal);//运维工单进行总数
        Integer workerCount = (int) taskList.stream().map(Task::getUserId).distinct().count();
        taskVo.setWorkerCount(workerCount);//运维工单处理人数
        taskVo.setRepair(b);
        taskVo.setDate(LocalDateTime.now().toString());
        return taskVo;
    }

    /**
     * 工单统计(SQL、xml版本)
     *
     * @param start 开始日期
     * @param end   结束日期
     * @return 返回工单查询结果
     */
    @Override
    public List<TaskVo> taskInfo(String start, String end) {
        // 1. 分别查两类工单统计
        TaskVo repairVo  = statVo(start, end, TYPE_REPAIR,  true);//true-运维工单, false-运营工单
        TaskVo operateVo = statVo(start, end, TYPE_OPERATE, false);

        // 2. 封装返回
        return Arrays.asList(operateVo, repairVo);
    }

    /* 查一类工单的聚合结果*/
    private TaskVo statVo(String start, String end, Integer type, boolean repair) {
        TaskVo vo = baseMapper.statByTypeBetween(start, end, type);
        // 最多一条记录

        // 没有数据时返回空对象（原始逻辑）
        if (ObjectUtil.isNull(vo)) {
            TaskVo empty = new TaskVo();
            empty.setTotal(0);
            empty.setCompletedTotal(0);
            empty.setCancelTotal(0);
            empty.setProgressTotal(0);
            empty.setWorkerCount(0);
            empty.setRepair(repair);
            empty.setDate(LocalDateTime.now().toString());
            return empty;
        }

        // 有数据时设置业务标记
        vo.setRepair(repair);          // 补充布尔标记
        vo.setDate(LocalDateTime.now().toString()); // 补充时间
        return vo;
    }
}

